<!--
  - Copyright (C) 2008 Google Inc.
  -
  - Licensed under the Apache License, Version 2.0 (the "License");
  - you may not use this file except in compliance with the License.
  - You may obtain a copy of the License at
  -
  -      http://www.apache.org/licenses/LICENSE-2.0
  -
  - Unless required by applicable law or agreed to in writing, software
  - distributed under the License is distributed on an "AS IS" BASIS,
  - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  - See the License for the specific language governing permissions and
  - limitations under the License.
 -->

<html>
<head>
<script src="../src/json_sans_eval.js"></script>
<script src="http://www.json.org/json2.js"></script>
<script src="http://www.json.org/json_parse.js"></script>
</head>
<body bgcolor=white>
<script>
function serialize(obj) {
  if (window.uneval) { return window.uneval(obj); }
  switch (typeof obj) {
  case 'object':
    if (obj === null) { return 'null'; }
    var js = [];
    if (obj instanceof Array) {
      js.push('[');
      for (var i = 0, n = obj.length; i < n; ++i) {
        i && js.push(', ');
        js.push(serialize(obj[i]));
      }
      js.push(']');
    } else {
      js.push('{');
      for (var k in obj) {
        js.length > 1 && js.push(', ');
        js.push(serialize(k), ': ', serialize(obj[k]));
      }
      js.push('}');
    }
    return js.join('');
  case 'string':
    return '"' + obj.replace('\\', '////').replace('\r', '\\r')
        .replace('\n', '\\n').replace('"', '\\"') + '"';
  default:
    return String(obj);
  }
}

function write(s, ok) {
  var pre;
  pre = document.createElement('PRE');
  if (ok !== undefined) {
    pre.style.color = ok ? '#080' : '#800';
  }
  pre.appendChild(document.createTextNode(s));
  document.body.appendChild(pre);
}

function runLater(f) {
  setTimeout(f, 0);
}

function test(json, opt_reviver) {
  runLater(function () {
      var o1 = jsonParse(json, opt_reviver);
      var o2 = JSON.parse(json, opt_reviver);
      var o3 = json_parse(json, opt_reviver);

      var t0 = (new Date).getTime();
      for (var i = 100; --i >= 0;) { jsonParse(json); }
      var t1 = (new Date).getTime();
      for (var i = 100; --i >= 0;) { JSON.parse(json); }
      var t2 = (new Date).getTime();
      for (var i = 50; --i >= 0;) { json_parse(json); }
      var t3 = (new Date).getTime();

      var dt0 = (t1 - t0) / 100, dt1 = (t2 - t1) / 100, dt2 = (t3 - t2) / 50;

      var serial1 = serialize(o1), serial2 = serialize(o2),
          serial3 = serialize(o3);

      var slowdown1 = (dt0 / dt1), slowdown2 = (dt0 / dt2);

      write('jsonParse (' + dt0 + '): ' + serial1, serial1 === serial2);
      write('JSON.Parse(' + dt1 + '): ' + serial2);
      write('json_parse(' + dt2 + '): ' + serial3);
      write('slowdown vs JSON        ' + slowdown1,
            slowdown1 < 1.5 ? true : slowdown1 > 3.0 ? false : void 0 );
      write('slowdown vs json_parse  ' + slowdown2,
            slowdown2 < 1.5 ? true : slowdown2 > 3.0 ? false : void 0 );
    });
}

function testFails(json) {
  runLater(function () {
             try {
               jsonParse(json);
             } catch (ex) {
               write('Error on ' + serialize(json), true);
               return;
             }
             write('Should error on ' + serialize(json), false);
           });
}


test('{}');
test('[]');
test('4');
test('{"x": 4, "y": 5}');
test('[1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6]');
test('{ "foo": null }');
test('{ "bar": false, "baz": true, "a\\nrr": [1, 2, 3, 4], "": "" }');
test('[ "grok", "zoicks", "\\"bother\\"", { "A": "\\u0020" }]');
test('["\ttab\tcharacter\tin\tstring"]');
test('[\n'
    + '   "JSON Test Pattern pass1",\n'
    + '   {"object with 1 member":["array with 1 element"]},\n'
    + '   {},\n'
    + '   [],\n'
    + '   -42,\n'
    + '   true,\n'
    + '   false,\n'
    + '   null,\n'
    + '   {\n'
    + '       "integer": 1234567890,\n'
    + '       "real": -9876.543210,\n'
    + '       "e": 0.123456789e-12,\n'
    + '       "E": 1.234567890E+34,\n'
    + '       "":  23456789012E66,\n'
    + '       "zero": 0,\n'
    + '       "one": 1,\n'
    + '       "space": " ",\n'
    + '       "quote": "\\"",\n'
    + '       "backslash": "\\\\",\n'
    + '       "controls": "\\b\\f\\n\\r\\t",\n'
    + '       "slash": "/ & \\/",\n'
    + '       "alpha": "abcdefghijklmnopqrstuvwyz",\n'
    + '       "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",\n'
    + '       "digit": "0123456789",\n'
    + '       "0123456789": "digit",\n'
    + '       "special": "`1~!@#$%^&*()_+-={\':[,]}|;.</>?",\n'
    + '       "hex": "\\u0123\\u4567\\u89AB\\uCDEF\\uabcd\\uef4A",\n'
    + '       "true": true,\n'
    + '       "false": false,\n'
    + '       "null": null,\n'
    + '       "array":[  ],\n'
    + '       "object":{  },\n'
    + '       "address": "50 St. James Street",\n'
    + '       "url": "http://www.JSON.org/",\n'
    + '       "comment": "// /* <!-- --",\n'
    + '       "# -- --> */": " ",\n'
    + '       " s p a c e d " :[1,2 , 3\n'
    + '\n'
    + ',\n'
    + '\n'
    + '4 , 5        ,          6           ,7        ],"compact":[1,2,3,4,5,6,7],\n'
    + '       "jsontext": "{\\"object with 1 member\\":[\\"array with 1 element\\"]}",\n'
    + '       "quotes": "&#34; \\u0022 %22 0x22 034 &#x22;",\n'
    + '       "\\/\\\\\\"\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"\n'
    + ': "A key can be any string"\n'
    + '   },\n'
    + '   0.5 ,98.6\n'
    + ',\n'
    + '99.44\n'
    + ',\n'
    + '\n'
    + '1066,\n'
    + '1e1,\n'
    + '0.1e1,\n'
    + '1e-1,\n'
    + '1e00,2e+00,2e-00\n'
    + ',"rosebud"]');
test('[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]');
test('{\n'
    + '   "JSON Test Pattern pass3": {\n'
    + '       "The outermost value": "must be an object or array.",\n'
    + '       "In this test": "It is an object."\n'
    + '   }\n'
    + '}');
testFails('"A JSON payload should be an object array, not a string."');
testFails('[[]');
testFails('[],[]');
test('[1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6, '
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6]');
test('[1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6, '
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6]');
test('[1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6, '
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6,'
     + '1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 12.34, 1e6]');
test('[{ "type": "date", "msSinceEpoch": 1234 }]',
     function (key, value) {
       if (value && 'object' === typeof value && value.type === 'date') {
         return new Date(value.msSinceEpoch);
       }
       return value;
     });
</script>
</body>
</html>
